package com.next

class Opportunity
{
    String serialNumber
    //商机号
    String name

    Double amount = 0

    Double probability = 0

    OpportunityStatus status

    String memo

    OpportunityStage stage
    OpportunityType type
    OpportunitySubtype subtype

    PurchasingMethod purchasingMethod

    LeadSource source

    Account account

    SortedSet contacts

    Territory territory

    ProductLine productLine
    Product product

    Date startTime
    Date endTime

    Lead lead

    CauseOfFailure causeOfFailure
    //失败原因
    String descriptionOfFailure
    //失败原因说明

    String externalId

    Contract contract

    User createBy
    User modifyBy
    User user

    Date createdDate = new Date()
    Date modifiedDate = new Date()

    static belongsTo = [account: Account, campaign: Campaign]

    static hasMany = [contacts: OpportunityContact, attachments: Attachment, notes: Note, activites: Activity, users: OpportunityTeam]

    Date externalModifiedDate
    //外部修改时间

    static constraints = {
        name nullable: true, blank: true
        campaign nullable: true, blank: true
        contract nullable: true, blank: true
        createdDate nullable: true, blank: true
        descriptionOfFailure nullable: true, blank: true, type: "text"
        endTime nullable: true, blank: true
        externalId nullable: true, blank: true //, unique: true
        externalModifiedDate nullable: true, blank: true
        lead nullable: true, blank: true
        memo nullable: true, blank: true
        modifiedDate nullable: true, blank: true
        serialNumber nullable: true, blank: true
        stage nullable: true, blank: true
        startTime nullable: true, blank: true
        subtype nullable: true, blank: true
        territory nullable: true, blank: true
        type nullable: true, blank: true
        source nullable: true, blank: true
        causeOfFailure nullable: true, blank: true
        createBy nullable: true, blank: true
        modifyBy nullable: true, blank: true
        user nullable: true, blank: true
        // productLine nullable: true, blank: true
        // product nullable: true, blank: true
        purchasingMethod nullable: true, blank: true
    }

    static mapping = {
        contacts(lazy: false)
    }

    String toString()
    {
        serialNumber
    }

    def springSecurityService

    def beforeInsert()
    {
        def username = springSecurityService?.getPrincipal()?.username
        createBy = User.findByUsername(username)
        if (!user)
        {
            user = createBy
        }
        String charset = (('A'..'Z') + ('0'..'9')).join()
        String s1 = org.apache.commons.lang.RandomStringUtils.random(3, charset)
        String s2 = org.apache.commons.lang.RandomStringUtils.random(3, charset)
        String s3 = org.apache.commons.lang.RandomStringUtils.random(3, charset)
        serialNumber = "${s1}-${s2}-${s3}"

        if (!name)
        {
            name = "${account}" + "${product}"
        }

        def company = Company.findAll()[0]
        if (company.enableContactTerritory && company.inheritanceAccountTerritory)
        {
            territory = account.territory
        }
        else if (company.enableContactTerritory)
        {
            territory = Territory.findByAccountAndProduct(account, product)
        }

        // 初始化 区域用户 权限
        if (territory)
        {
            def territoryTeam = TerritoryTeam.findByTerritory(territory)
            territoryTeam?.each {
                def opportunityTeam = new OpportunityTeam(opportunity: this, user: it?.user, teamRole: it?.teamRole,
                                                          contactPermission: it?.contactPermission,
                                                          activityPermission: it?.activityPermission,
                                                          teamPermission: it?.teamPermission,
                                                          attachmentPermission: it?.attachmentPermission,
                                                          notePermission: it?.notePermission,
                                                          flexFieldPermission: it?.flexFieldPermission,
                                                          addressPermission: it?.addressPermission)
                this.addToUsers(opportunityTeam)
            }
        }

        // 初始化 上级用户 权限
        if (user.shareOpportunityToSupervisor)
        {
            User reportTo = user.reportTo
            while (reportTo)
            {
                def flag = true
                users?.each {
                    if (reportTo == it?.user)
                    {
                        flag = false
                    }
                }

                if (flag)
                {
                    OpportunityTeam opportunityTeam = new OpportunityTeam(opportunity: this, user: reportTo, teamRole: TeamRole.findByName('Read'),
                                                                          contactPermission: TeamRole.findByName('Read'),
                                                                          activityPermission: TeamRole.findByName('Read'),
                                                                          teamPermission: TeamRole.findByName('Read'),
                                                                          attachmentPermission: TeamRole.findByName('Read'),
                                                                          notePermission: TeamRole.findByName('Read'),
                                                                          flexFieldPermission: TeamRole.findByName('Read'),
                                                                          addressPermission: TeamRole.findByName('Read'))
                    this.addToUsers(opportunityTeam)
                }

                reportTo = reportTo.reportTo
            }
        }

        // 初始化 所有者 权限
        def flag = true
        users?.each {
            if (user == it?.user)
            {
                flag = false
            }
        }

        if (flag)
        {
            OpportunityTeam opportunityTeam = new OpportunityTeam(opportunity: this, user: user, teamRole: TeamRole.findByName('Edit'),
                                                                  contactPermission: TeamRole.findByName('Edit'),
                                                                  activityPermission: TeamRole.findByName('Edit'),
                                                                  teamPermission: TeamRole.findByName('Edit'),
                                                                  attachmentPermission: TeamRole.findByName('Edit'),
                                                                  notePermission: TeamRole.findByName('Edit'),
                                                                  flexFieldPermission: TeamRole.findByName('Edit'),
                                                                  addressPermission: TeamRole.findByName('Edit'))
            this.addToUsers(opportunityTeam)
        }
    }

    def afterInsert()
    {
        def flexFieldCategories = FlexFieldCategory.findAllByObjectType('Opportunity')
        flexFieldCategories?.each {
            if (it?.condition)
            {
                def result = false
                try
                {
                    def shell = new GroovyShell()
                    def closure = shell.evaluate(it?.condition?.script)
                    result = closure(this)
                }
                catch (Exception e)
                {
                    log.error e
                }
                if (result)
                {
                    initFlexField(it)
                }
            }
            else
            {
                initFlexField(it)
            }
        }
    }

    def initFlexField(FlexFieldCategory flexFieldCategory)
    {
        def fields = FlexField.findAllByCategory(flexFieldCategory)
        fields?.each {
            def field = new FlexFieldInstance(category: flexFieldCategory, field: it, opportunity: this)
            field.save()
        }
    }

    def beforeUpdate()
    {
        modifiedDate = new Date()
        def username = springSecurityService?.getPrincipal()?.username
        modifyBy = User.findByUsername(username)

        def flag = true
        users?.each {
            if (user == it?.user)
            {
                flag = false
            }
        }

        if (flag)
        {
            OpportunityTeam opportunityTeam = new OpportunityTeam(opportunity: this, user: user, teamRole: TeamRole.findByName('Edit'),
                                                                  contactPermission: TeamRole.findByName('Edit'),
                                                                  activityPermission: TeamRole.findByName('Edit'),
                                                                  teamPermission: TeamRole.findByName('Edit'),
                                                                  attachmentPermission: TeamRole.findByName('Edit'),
                                                                  notePermission: TeamRole.findByName('Edit'),
                                                                  flexFieldPermission: TeamRole.findByName('Edit'),
                                                                  addressPermission: TeamRole.findByName('Edit'))
            this.addToUsers(opportunityTeam)
        }

        def opportunityHistory = new OpportunityHistory()
        opportunityHistory.account = account
        opportunityHistory.campaign = campaign
        opportunityHistory.causeOfFailure = causeOfFailure
        opportunityHistory.endTime = endTime
        opportunityHistory.externalModifiedDate = externalModifiedDate
        opportunityHistory.startTime = startTime
        opportunityHistory.amount = amount
        opportunityHistory.probability = probability
        opportunityHistory.lead = lead
        opportunityHistory.source = source
        opportunityHistory.stage = stage
        opportunityHistory.status = status
        opportunityHistory.subtype = subtype
        opportunityHistory.type = type
        opportunityHistory.product = product
        opportunityHistory.productLine = productLine
        opportunityHistory.purchasingMethod = purchasingMethod
        opportunityHistory.descriptionOfFailure = descriptionOfFailure
        opportunityHistory.externalId = externalId
        opportunityHistory.memo = memo
        opportunityHistory.serialNumber = serialNumber
        opportunityHistory.territory = territory
        opportunityHistory.user = user
        opportunityHistory.parent = this

        opportunityHistory.createBy = createBy
        opportunityHistory.createdDate = new Date()

        opportunityHistory.save()
    }
}
